#include "mainwindow.h"
#include <iostream>
#include "ui_mainwindow.h"
#include "../../IsoGraphEditDistance.hpp"
#include <QMessageBox>
#include <QInputDialog>
#include "SingleGraphClusterer.hpp"

//using namespace dlib;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_iIDCounter = 0;
    m_pLastSelected = 0;

    m_MetaGraphLItem = new QTreeWidgetItem( ui->graphTree);
    m_ClustersLItem = new QTreeWidgetItem( ui->graphTree);
    m_GraphsLItem = new QTreeWidgetItem( ui->graphTree);
    m_OwnGraphsLItem = new QTreeWidgetItem( ui->graphTree);
    m_FreqSubGraphsLItem = new QTreeWidgetItem( ui->graphTree );
    m_PSubgraphs = new QTreeWidgetItem( ui->graphTree );
    m_PartialGraphsExamples = new QTreeWidgetItem( ui->graphTree );


    m_MetaGraphLItem->setText(0, QApplication::translate("MainWindow", "MetaGraph", 0, QApplication::UnicodeUTF8));
    m_ClustersLItem->setText(0, QApplication::translate("MainWindow", "Clusters", 0, QApplication::UnicodeUTF8));
    m_GraphsLItem->setText(0, QApplication::translate("MainWindow", "Graphs", 0, QApplication::UnicodeUTF8));
    m_OwnGraphsLItem->setText(0, QApplication::translate("MainWindow", "Created graphs", 0, QApplication::UnicodeUTF8));
    m_PSubgraphs->setText(0, QApplication::translate("MainWindow", "PG Subgraphs", 0, QApplication::UnicodeUTF8));
    m_PartialGraphsExamples->setText(0, QApplication::translate("MainWindow", "Partial graphs", 0, QApplication::UnicodeUTF8));

    //connect(ui->graphTree,SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(GraphItemclicked(QTreeWidgetItem*, int)));
    connect(ui->graphTree,SIGNAL(itemSelectionChanged()), this, SLOT(GraphItemclicked()));
    m_pGraphTree = ui->graphTree;

    //ui->graphTree

    connect( ui->addVertexButton, SIGNAL( clicked() ), this, SLOT( on_newVertex() ) );
    connect( ui->addEdgeButton, SIGNAL( clicked() ), this, SLOT( on_newEdge() ) );
    connect( ui->nStep, SIGNAL( clicked() ), this, SLOT( on_nStep() ) );
    connect( ui->nPrediction, SIGNAL( clicked() ), this, SLOT( on_nPrediction() ) );
    connect( ui->newRndG, SIGNAL( clicked() ), this, SLOT( on_newRndG() ) );
    connect( ui->moveBtn, SIGNAL( clicked() ), this, SLOT( on_moveBtn() ) );
    connect( ui->nBFPredict, SIGNAL( clicked() ), this, SLOT( on_nBFPrediction() ) );

    //ui->graphicsView->setPixmap(QPixmap::fromImage(image));

    //connect(ui->graphTree, SIGNAL(itemChanged(QTreeWidgetItem *)),
    //        this, SLOT(GraphItemclicked2(QTreeWidgetItem *)));


    QGraphicsView* w = new QGraphicsView();
    m_Scn = new QGraphicsScene( ui->graphView );
    m_Scn->setSceneRect( 0,0, 2000, 1000 );
    ui->graphView->setScene( m_Scn );
   // w->setFixedSize( 400, 400 );
    QPixmap pix( "test.png" );
    m_Pic = m_Scn->addPixmap( pix );
    //m_Scn->removeItem((QGraphicsItem*)&pix);

    //QPixmap pix( "test.png" );
    //ui->graphView->addPixmap( QPixmap::fromImage(image) );
    //ui->graphicsView-

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::PopulateGraphTree()
{


    //graphMap.clear();


    //m_OwnGraphsLItem->clear();
    qDeleteAll(m_OwnGraphsLItem->takeChildren());
    for( int i = 0; i < m_OwnGraphs.size(); i++ )
    {
        //m_OwnGraphsLItem->
        GraphHandler::Graph& G = m_OwnGraphs[i];
        std::string sName = boost::get_property(G,boost::graph_name);
       // std::string sName;

        // Create a new widget item
        QTreeWidgetItem* pNewItem = new QTreeWidgetItem( m_OwnGraphsLItem );
       // pNewItem->setText(0, QApplication::translate("MainWindow", sName, 0, QApplication::UnicodeUTF8));
        pNewItem->setText(0, QString::fromStdString(sName));

        graphMap[pNewItem] = &G;
    }

//GraphHandler::Instance().GSpan(GraphHandler::Instance().GetGraphVector(), 0.1);
    //std::vector<GSpanStruct> kTmp = GraphHandler::Instance().LoadGSpanData("test2.dat.fp");
    std::vector<GSpanStruct> kTmp = GraphHandler::Instance().GSpan(GraphHandler::Instance().GetGraphVector(), 0.2); // "test2.dat.fp");


    return;
    //GraphHandler::Instance().GenerateFrequentEditMaps(kTmp);

    //ofstream out("CorrelationMatrix", ios_base::out);

    cout << kTmp.size() << endl;
    vector< pair< pair<int, int>, double > > dCorrelations;
    for(int i=0; i < kTmp.size(); i++)
    {
        for(int j=i; j < kTmp.size(); j++)
        {

        if( !GraphHandler::Instance().IsSubgraphIsomorph(kTmp[i].G, kTmp[j].G) && !GraphHandler::Instance().IsSubgraphIsomorph(kTmp[j].G, kTmp[i].G) )
        {
            double dCorr = GraphHandler::Instance().GetGraphCorrelation(kTmp[i].G, kTmp[j].G);
            dCorrelations.push_back( make_pair( make_pair(i,j), dCorr ) );
            //cout << i << "," << j << ", dCorr: " << dCorr << endl;
        }
        }
        cout << i << endl;
    }

    sort(dCorrelations.begin(), dCorrelations.end(), sort_pred< pair<int, int> >());
    for(int i=0; i < dCorrelations.size(); i++)
        cout << dCorrelations[i].first.first << ", " << dCorrelations[i].first.second << ", dCorr: " << dCorrelations[i].second << endl;


    std::vector< std::pair<GSpanStruct*,double> > kTmp2;
    int iTotalGraphs = GraphHandler::Instance().GetGraphVector().size();
    for(int i= 0; i< kTmp.size(); i++)
    {
        //if( num_vertices(kTmp[i].G) >= 6 )
        kTmp2.push_back( make_pair(&kTmp[i], (double)kTmp[i].iSupport / (double)iTotalGraphs) );
    }
    //sort(kTmp2.begin(), kTmp2.end(), sort_pred<GSpanStruct*>());

    for(int i= 0; i< kTmp2.size(); i++)
    {
        stringstream sName;

        sName << "FSubgraph " << i << ", Supp: " << kTmp2[i].second;
        QTreeWidgetItem* pNewItem = new QTreeWidgetItem( m_FreqSubGraphsLItem );
        pNewItem->setText(0, QString::fromStdString(sName.str()));

        freqsubgraphMap[pNewItem] = *kTmp2[i].first;//kTmp[i];
    }



   // m_Clusters = GraphHandler::Instance().StructureClustering(0.1, 4);
    //m_Clusters = GraphHandler::Instance().StructureClustering(0.1, 4);



    //cout << "Done." << endl;
    //clusterMap.clear();
    for( int i = 0; i < m_Clusters.size(); i++ )
    {
       // AddCluster(m_Clusters[i], m_ClustersLItem);

    }

    for( int i = 0; i < GraphHandler::Instance().GetNumGraphs(); i++ )
    {
        GraphHandler::Graph& G = GraphHandler::Instance().GetGraph(i);
        std::string sName = boost::get_property(G,boost::graph_name);
       // std::string sName;

        // Create a new widget item
        QTreeWidgetItem* pNewItem = new QTreeWidgetItem( m_GraphsLItem );
       // pNewItem->setText(0, QApplication::translate("MainWindow", sName, 0, QApplication::UnicodeUTF8));
        pNewItem->setText(0, QString::fromStdString(sName));


        graphMap[pNewItem] = &G;

/*
        // Now, lets add all the (meta)clusters in which this graph occurs
        for( int j=0; j < m_Clusters.size(); j++ )
        {
            if( std::find(m_Clusters[j].begin(), m_Clusters[j].end(), &G)!=m_Clusters[j].end() )
            {
                QTreeWidgetItem* pNewItem1 = new QTreeWidgetItem( pNewItem );
               // pNewItem->setText(0, QApplication::translate("MainWindow", sName, 0, QApplication::UnicodeUTF8));
                pNewItem1->setText(0, "Metacluster"); //QString::fromStdString(sName));
                graphMap[pNewItem1] = &GraphHandler::Instance().kCommon[j];
            }
        }*/
    }

}

void MainWindow::AddCluster(Cluster* pC, QTreeWidgetItem* pRoot)
{
   // if( pC->pGraphs.size() > 1 )
   // {
        // Create the new item as well as the maps to it
        QTreeWidgetItem* pNewItem = new QTreeWidgetItem( pRoot );
        QTreeWidgetItem* pCluster = pNewItem;
        clusterMap[pNewItem] = pC;
        graphMap[pNewItem] = &pC->kMeta; //&GraphHandler::Instance().kCommon[i];

        // Generate the cluster name and set it
        std::stringstream sName;
        sName << "Cluster ";
        pNewItem->setText(0, QString::fromStdString(sName.str()));

        QTreeWidgetItem* pNewItemGraph = new QTreeWidgetItem( pNewItem );
        pNewItemGraph->setText(0, "Meta cluster");
        graphMap[pNewItemGraph] = &pC->kMeta; //&GraphHandler::Instance().kCommon[i];

       // for( int j=0; j < m_Clusters[i].size(); j++ )
        for( int j=0; j < pC->pGraphs.size(); j++ )
        {
            QTreeWidgetItem* pNewItemGraph = new QTreeWidgetItem( pNewItem );
            //std::string sName = boost::get_property(*pC->pGraphs[j],boost::graph_name);
            std::string sName = boost::get_property(GraphHandler::Instance().GetGraph(pC->pGraphs[j]),boost::graph_name);
            pNewItemGraph->setText(0, QString::fromStdString(sName));

            //graphMap[pNewItemGraph] = pC->pGraphs[j];
            graphMap[pNewItemGraph] = &GraphHandler::Instance().GetGraph(pC->pGraphs[j]);
        }

        for( int j=0; j < pC->pChildren.size(); j++ )
        {
            AddCluster(pC->pChildren[j], pCluster);
        }
  //  }
}

void MainWindow::DisplayGraph(const GraphHandler::Graph& G, const GraphHandler::Graph* pOverlay)
{
    std::vector<const GraphHandler::Graph*> kTmp;
    if( pOverlay != 0)
        kTmp.push_back(pOverlay);
    DisplayGraph(G, kTmp);
}

void MainWindow::DisplayGraph(const GraphHandler::Graph& G, std::vector<const GraphHandler::Graph*> pOverlay)
{
/*
    SingleGraphClusterer::ClusterGraph(G);
    system ("dot -Tpng tmpcluster.dot -o test.png");

    QPixmap pix( "test.png" );
    m_Scn->removeItem((QGraphicsItem*)m_Pic);
    m_Pic = m_Scn->addPixmap( pix );*/


    GraphHandler::Instance().SaveGraph("tmp.dot",G, pOverlay);

    system ("dot -Tpng tmp.dot -o test.png");

    QPixmap pix( "test.png" );
    m_Scn->removeItem((QGraphicsItem*)m_Pic);
    m_Pic = m_Scn->addPixmap( pix );
}

//void MainWindow::GraphItemclicked(QTreeWidgetItem* selection, int col)
void MainWindow::GraphItemclicked()
{
    //QList<QTreeWidgetItem *> QTreeWidget::selectedItems () const
    QTreeWidgetItem* selection = m_pGraphTree->selectedItems().front();


    //cout << m_pLastSelected << " curr: " << m_pCurrentSelected << endl;
    m_pLastSelected = m_pCurrentSelected;
    m_pCurrentSelected = selection;

    if( m_pLastSelected != 0 && m_pCurrentSelected != 0 )
    {
        if( graphMap.find(selection) != graphMap.end() && graphMap.find(m_pLastSelected) != graphMap.end() )
        {
            stringstream sTxt;
            sTxt << m_pLastSelected << " curr: " << m_pCurrentSelected << ", ";
            sTxt << "Distance: " << GraphHandler::Instance().EditDistance(*graphMap[m_pCurrentSelected], *graphMap[m_pLastSelected]);
            ui->labDistance->setText(QString::fromStdString(sTxt.str()));

            GraphHandler::Graph gTmp = GraphHandler::Instance().LargestCommonSubGraph(*graphMap[m_pCurrentSelected], *graphMap[m_pLastSelected]);
            GraphHandler::Instance().SaveGraph("debugsub.dot", gTmp);

            bool bTmp = GraphHandler::Instance().IsSubgraphIsomorph(*graphMap[m_pCurrentSelected], *graphMap[m_pLastSelected]);
            cout << bTmp << endl;

        }

        if( freqsubgraphMap.find(selection) != freqsubgraphMap.end() && freqsubgraphMap.find(m_pLastSelected) != freqsubgraphMap.end() )
        {
            /*
    int FindClusterID(const Cluster* pC) const;
    GetClusterCorrelation
              */
            //freqsubgraphMap[selection].G
            stringstream sTxt;
            sTxt << "Correlation: " << GraphHandler::Instance().GetGraphCorrelation(freqsubgraphMap[selection].G, freqsubgraphMap[m_pLastSelected].G);
            ui->labDistance->setText(QString::fromStdString(sTxt.str()));
        }
    }

    if( graphMap.find(selection) != graphMap.end() && selection == m_PSubgraphs )
        ShowPrediction(*graphMap[selection]);

    if( graphMap.find(selection) != graphMap.end() )
    {
        // Clicked on a graph


        if( selection->parent() != 0 )
        {
            // So we clicked on a graph belonging to a cluster, highlight common subgraph
            //if( m_PSubgraphs )
            bool bHyp = false;
            if( selection == m_PSubgraphs )
                bHyp = true;
            for(int i=0; i < m_PSubgraphs->childCount(); i++)
                if( m_PSubgraphs->child(i) == selection )
                {
                    bHyp = true;
                    break;
                }

            cout << "bHyp: " << bHyp << endl;
                if( !bHyp )
                    DisplayGraph(*graphMap[selection], graphMap[selection->parent()]);
                else
                    ShowPrediction(*graphMap[selection]);

        }
        else
            DisplayGraph(*graphMap[selection]);

    }
    else if( clusterMap.find(selection) != clusterMap.end() )
    {
        // Clicked on a cluster
        //LargestCommonSubGraph, std::vector<GraphHandler::Graph*>
        //cout << "Cluster map: " << clusterMap[selection];
        //cout << "size: " << clusterMap[selection]->size();
        //cout.flush();

        //GraphHandler::Graph gTmp = *((*clusterMap[selection])[0]);
        //for(int i=1; i<clusterMap[selection]->size(); i++)
        //{
        //    gTmp = GraphHandler::Instance().LargestCommonSubGraph(gTmp, *((*clusterMap[selection])[i]));
        //}
        //DisplayGraph(gTmp);
    }
    else if( freqsubgraphMap.find(selection) != freqsubgraphMap.end() )
    {
        DisplayGraph(freqsubgraphMap[selection].G);
    }
    /*
      pair<unsigned int, GraphHandler::Graph>
      m_PGExamplesMap[pNewItemGraph] = pgs[i];//&((*it).first);
      */
    else if( m_PGExamplesMap.find(selection) != m_PGExamplesMap.end() )
    {
        GraphHandler::Instance().m_pEGraph = &GraphHandler::Instance().GetGraph(m_PGExamplesMap[selection].first);
        GraphHandler::Instance().m_kPartialG = m_PGExamplesMap[selection].second;
        GraphHandler::Instance().iExcludeGraph = m_PGExamplesMap[selection].first;

        DisplayGraph(*GraphHandler::Instance().m_pEGraph,&GraphHandler::Instance().m_kPartialG);
    }

}
/*
// Clusters into k different clusters
void MainWindow::Cluster(int iK, std::vector<GraphHandler::Graph>& kGraphs)
{
    typedef matrix<double,0,1> sample_type;


    typedef radial_basis_kernel<sample_type> kernel_type;


    //kcentroid<kernel_type> kc(kernel_type(0.1),0.01,40);
    kcentroid<kernel_type> kc(kernel_type(0.1),dSens,iDictSize);

    kkmeans<kernel_type> test(kc);

    std::vector<sample_type> samples;
    std::vector<sample_type> initial_centers;

    sample_type m;


    //ofstream fs;
    //fs.open( "data" );

    int iN = kGraphs.size();//GraphHandler::Instance().GetNumGraphs();

    for(int i = 0; i < iN; i++ )
    {
        cout << "i: " << i << endl;
        for(int j = 0; j < iN; j++ )
        {
            m.set_size(iN);
           // cout << "j: " << j << endl;
            //m(j) = IsoGraphEditDistance::GraphEditDistance(kGraphs[i], kGraphs[j]);
           // return 1.0 - (double)(iMax)/
          //   ( (double)num_vertices(G1) + (double)num_vertices(G2) - (double)(iMax) );
            m(j) = (double)(GraphHandler::Instance().EditDistance(kGraphs[i], kGraphs[j])) / sqrt((double)iN);
            //cout << "m(j):" << m(j) << endl;
           // m(j) = IsoGraphEditDistance::GraphEditDistance(kGraphs[i], kGraphs[j]);
            //int iD = GraphHandler::Instance().EditDistance(kGraphs[i], kGraphs[j]);
            //m(j) = 1.0 - (double)(iD)/
            // ( (double)num_vertices(kGraphs[i]) + (double)num_vertices(kGraphs[j]) - (double)(iD) );
            //cout << m(j) << endl;
            //fs << m(j) << " ";
        }
        //fs << endl;
        samples.push_back(m);
    }

    //fs.close();

    test.set_number_of_centers(iK);

    // You need to pick some initial centers for the k-means algorithm.  So here
    // we will use the dlib::pick_initial_centers() function which tries to find
    // n points that are far apart (basically).
    pick_initial_centers(iK, initial_centers, samples, test.get_kernel());

    // now run the k-means algorithm on our set of samples.
    test.train(samples,initial_centers);


    m_Clusters.clear();
    m_Clusters.reserve(iK);

    for(int i=0; i<iK; i++)
    {
        m_Clusters.push_back(std::vector<GraphHandler::Graph*>());

        // Create a cluster
        QTreeWidgetItem* pNewItem = new QTreeWidgetItem( m_ClustersLItem );
        std::stringstream sName;
        sName << "Cluster " << i;
        pNewItem->setText(0, QString::fromStdString(sName.str()));
        clusterMap[pNewItem] = &m_Clusters[i];


        for (unsigned long j = 0; j < samples.size(); ++j)
        {
            if( test(samples[j]) == i )
            {
                cout << "Adding to cluster " << i << endl;
                m_Clusters[i].push_back(&kGraphs[j]);

                QTreeWidgetItem* pNewItemGraph = new QTreeWidgetItem( pNewItem );
                std::string sName = boost::get_property(kGraphs[j],boost::graph_name);
                pNewItemGraph->setText(0, QString::fromStdString(sName));
                graphMap[pNewItemGraph] = &kGraphs[j];
            }
        }
    }

    // now loop over all our samples and print out their predicted class.  In this example
    // all points are correctly identified.
    for (unsigned long i = 0; i < samples.size(); ++i)
    {
       // cout << test(samples[i]) << " ";
    }

    // We will now create a list of all the clusters, with lists of pointers to the containing graphs


}
*/


void MainWindow::on_actionCreate_new_graph_triggered()
{
   // m_OwnGraphs.push_back(NewGraph());
    NewGraph();
}

GraphHandler::Graph& MainWindow::NewGraph()
{
    m_OwnGraphs.push_back(GraphHandler::Graph());
    GraphHandler::Graph* p =  &(m_OwnGraphs[m_OwnGraphs.size()-1]); //new GraphHandler::Graph();


    QTreeWidgetItem* pNewItem = new QTreeWidgetItem( m_OwnGraphsLItem );
    std::stringstream sName;
    sName << "Graph " << m_OwnGraphs.size();
    pNewItem->setText(0, QString::fromStdString(sName.str()));

    set_property(*p, boost::graph_name, sName.str());

    graphMap[pNewItem] = p;//&(m_OwnGraphs[m_OwnGraphs.size()-1]);

    return *p;
}

void MainWindow::on_newVertex()
{
   // m_pCurrentSelected
    GraphHandler::Graph& G = *graphMap[m_pCurrentSelected];
    std::string sName = ui->vertexNameEdit->text().toStdString();

    addVertex(G, sName);

    //GraphItemclicked(m_pCurrentSelected, 0);
    m_pGraphTree->setCurrentItem(m_pCurrentSelected);
    GraphItemclicked();

    //GraphHandler::Vertex v
    //ui->vertexNameEdit->text
}

void MainWindow::addVertex(GraphHandler::Graph& G, std::string sName)
{
    GraphHandler::Vertex V = add_vertex(G);


    //G[V].sName = sName;

    if( m_NameMap.find(sName) == m_NameMap.end() )
    {
        m_NameMap[sName] = m_iIDCounter;
        m_iIDCounter++;
    }

    put(vertex_name, G, V, m_NameMap[sName]);
}

void MainWindow::on_newEdge()
{
    GraphHandler::Graph& G = *graphMap[m_pCurrentSelected];

    std::string sU = ui->labU->text().toStdString();
    std::string sV = ui->labV->text().toStdString();

    addEdge(G, sU, sV);

    //GraphItemclicked(m_pCurrentSelected, 0);
    m_pGraphTree->setCurrentItem(m_pCurrentSelected);
    GraphItemclicked();
}

void MainWindow::addEdge(GraphHandler::Graph& G, std::string sU, std::string sV)
{
    std::pair<bool, GraphHandler::Iter_t> U = GraphHandler::Instance().FindVertex(sU,G);
    std::pair<bool, GraphHandler::Iter_t> V = GraphHandler::Instance().FindVertex(sV,G);

    if( U.first && V.first )
        add_edge(*U.second, *V.second, G);
}

void MainWindow::GenerateRandomGraph(GraphHandler::Graph& G,std::vector<std::string>& sNames, std::vector< std::vector<double> >& kMarkov)
{
    //srand ( time(NULL) );



    int iN = sNames.size();//1 + std::rand() % (sNames.size());

    //if( iN > sNames.size() ) iN = sNames.size();

    std::vector<std::string> sNamesTmp = sNames;
    std::vector<std::string> kResNames;


    // Add vertices in random
    /*
    for(int i = 0; i < iN; i++)
    {
        int r = std::rand() % sNamesTmp.size();
        addVertex(G, sNamesTmp[r]);
        kResNames.push_back(sNamesTmp[r]);

        //std::find(sNamesTmp.begin(), sNamesTmp.end(), sNamesTmp[r])
        sNamesTmp.erase(std::find(sNamesTmp.begin(), sNamesTmp.end(), sNamesTmp[r]));
    }*/

    for(int i = 0; i < iN; i++)
    {
        addVertex(G, sNamesTmp[i]);
        kResNames.push_back(sNamesTmp[i]);
    }

    for(int i = 0; i < iN; i++)
    {
        for(int j = 0; j < iN - i; j++)
        {
            // First check that this vertex combination is valid, i.e. that it exist
            if( std::find(kResNames.begin(), kResNames.end(), sNames[i]) != kResNames.end() &&
                    std::find(kResNames.begin(), kResNames.end(), sNames[j]) != kResNames.end() )
            {
                // Now see if we are "lucky" enough to have this edge
                int r = std::rand() % 100;

                if( r < (int) (kMarkov[i][j] * 100.0) )
                    addEdge(G, *(std::find(kResNames.begin(), kResNames.end(), sNames[i])),
                            *(std::find(kResNames.begin(), kResNames.end(), sNames[j])) );
            }

        }
    }


}

void MainWindow::on_actionCalculate_distance_triggered()
{
    // Assume its between owngraph 0 and 1
    cout << "Distance: " << GraphHandler::Instance().EditDistance(m_OwnGraphs[0], m_OwnGraphs[1]) << endl;
    cout.flush();
}

void MainWindow::on_nStep()
{
    GraphHandler::Instance().ExampleStepNext();
    //DisplayGraph(GraphHandler::Instance().m_kPartialG);
    DisplayGraph(*GraphHandler::Instance().m_pEGraph,&GraphHandler::Instance().m_kPartialG);
    graphMap[m_PSubgraphs] = &GraphHandler::Instance().m_kPartialG;
    clusterMap[m_PSubgraphs] = new Cluster();


}

void MainWindow::ShowPrediction(const GraphHandler::Graph& G)
{
    std::list<const GraphHandler::Graph*> kTmp;
    kTmp.push_back(&G);
    kTmp.push_back(GraphHandler::Instance().m_pEGraph);

    std::vector<const GraphHandler::Graph*> kOverlay;
    kOverlay.push_back(&GraphHandler::Instance().m_kPartialG);
    kOverlay.push_back(&G);
    kOverlay.push_back(GraphHandler::Instance().m_pEGraph);

    // Yellow means it is predicted and in the partial
    // Red means its only in the partial and not in the predicted
    // Green means its predicted

    GraphHandler::Instance().SaveGraph("hyp.dot", G);
    GraphHandler::Instance().SaveGraph("partialgraph.dot", GraphHandler::Instance().m_kPartialG);

    DisplayGraph(GraphHandler::Instance().GraphUnion(kTmp), kOverlay);
}

void MainWindow::on_nPrediction()
{
    //kLastPrediction = GraphHandler::Instance().ExampleStepPredict4();
    kLastPrediction = GraphHandler::Instance().ExampleStepPredict2();
    //kLastPrediction = GraphHandler::Instance().BruteForcePredict();
    ShowPrediction(kLastPrediction);

    //return;
    kMoveGraph = GraphHandler::Instance().m_kPartialG;



    graphMap.clear();

    qDeleteAll(m_PSubgraphs->takeChildren());

    if( GraphHandler::Instance().m_kPSubgraphs.size() != 0  )
    {
        //std::vector< pair<GraphHandler::Graph, double> >& hyps = GraphHandler::Instance().m_kHypothesis;
        std::vector< GraphHandler::Graph >& hyps = GraphHandler::Instance().m_kPSubgraphs;

        graphMap[m_PSubgraphs] = &kLastPrediction;
        //for( std::vector< pair<GraphHandler::Graph, double> >::iterator it=hyps.begin(); it!=hyps.end(); ++it )
        for( int i=0; i < hyps.size(); i++)
        {
            stringstream sName;
            sName << "Hyp, S: " << GraphHandler::Instance().m_iHypSupport[i];// P: " << it->second;
            QTreeWidgetItem* pNewItemGraph = new QTreeWidgetItem( m_PSubgraphs );
            pNewItemGraph->setText(0, QString::fromStdString(sName.str()));

            graphMap[pNewItemGraph] = &(hyps[i]);//&((*it).first);
        }
    }

}
void MainWindow::on_newRndG()
{
    int i = GraphHandler::Instance().GenerateTestExample();
    SetGraphNumber(i);
    GraphHandler::Instance().iExcludeGraph = i;
    DisplayGraph(*GraphHandler::Instance().m_pEGraph,&GraphHandler::Instance().m_kPartialG);
    kMoveGraph = GraphHandler::Graph();
}

void MainWindow::on_moveBtn()
{

    if( num_vertices(kMoveGraph) == 0 )
        kMoveGraph = GraphHandler::Instance().m_kPartialG;

    kLastPrediction = GraphHandler::Instance().ExampleStepPredict2(&kMoveGraph);

    ShowPrediction(kLastPrediction);

    kMoveGraph = kLastPrediction;



    //---------------
    /*
    graphMap.clear();
    qDeleteAll(m_PSubgraphs->takeChildren());
    if( GraphHandler::Instance().m_kHypothesis.size() != 0  )
    {
        std::vector< pair<GraphHandler::Graph, double> >& hyps = GraphHandler::Instance().m_kHypothesis;

        graphMap[m_PSubgraphs] = &kLastPrediction;
        for( std::vector< pair<GraphHandler::Graph, double> >::iterator it=hyps.begin(); it!=hyps.end(); ++it )
        {
            stringstream sName;
            sName << "Hyp P: " << it->second;
            QTreeWidgetItem* pNewItemGraph = new QTreeWidgetItem( m_PSubgraphs );
            pNewItemGraph->setText(0, QString::fromStdString(sName.str()));

            graphMap[pNewItemGraph] = &((*it).first);
        }
    }*/


}


void MainWindow::on_actionBlacklist_vertex_triggered()
{
    bool ok;
    QString textstring = QInputDialog::getText(this, "Enter vertex name","",QLineEdit::Normal,QString::null,&ok);
    if (ok && !textstring.isEmpty())
    {
        //cout << textstring.toStdString() << endl;
        set<string> sBlacklist;
        sBlacklist.insert(textstring.toStdString());
        GraphHandler::Instance().Blacklist(sBlacklist);
        cout << "Blacklisted " << textstring.toStdString() << endl;
        GraphHandler::Instance().GenerateTestExample(true);
        DisplayGraph(*GraphHandler::Instance().m_pEGraph,&GraphHandler::Instance().m_kPartialG);
    }

}

void MainWindow::SetGraphNumber(int i)
{
    m_iCurrentGraphID = i;

    stringstream sTxt;
    sTxt << "Graph ID: " << i;
    ui->lGraphInfo->setText(QString::fromStdString(sTxt.str()));
}

void MainWindow::on_actionSelect_start_vertex_triggered()
{

    bool ok;
    QString textstring = QInputDialog::getText(this, "Enter vertex name","",QLineEdit::Normal,QString::null,&ok);
    if (ok && !textstring.isEmpty())
    {
        string sName = textstring.toStdString();

        GraphHandler::Instance().GenerateTestExample(true, -1, &sName);
        DisplayGraph(*GraphHandler::Instance().m_pEGraph,&GraphHandler::Instance().m_kPartialG);
    }
    //sVertexName
}

void MainWindow::on_actionSelect_graph_triggered()
{
    bool ok;
    QString textstring = QInputDialog::getText(this, "Enter graph ID","",QLineEdit::Normal,QString::null,&ok);
    if (ok && !textstring.isEmpty())
    {
        string sId = textstring.toStdString();
        int iID = lexical_cast<int>(textstring.toStdString());

        SetGraphNumber(GraphHandler::Instance().GenerateTestExample(false, iID));
        DisplayGraph(*GraphHandler::Instance().m_pEGraph,&GraphHandler::Instance().m_kPartialG);
    }
}

void MainWindow::on_nBFPrediction()
{
    kLastPrediction = GraphHandler::Instance().BruteForcePredict();
    ShowPrediction(kLastPrediction);

    //return;
    kMoveGraph = GraphHandler::Instance().m_kPartialG;
}

void MainWindow::AddPartialGraphs(vector< pair<unsigned int, GraphHandler::Graph> > pgs)
{
    for(int i=0; i < pgs.size(); i++)
    {
        stringstream sName;
        sName << "Example";// P: " << it->second;
        QTreeWidgetItem* pNewItemGraph = new QTreeWidgetItem( m_PartialGraphsExamples );
        pNewItemGraph->setText(0, QString::fromStdString(sName.str()));

        m_PGExamplesMap[pNewItemGraph] = pgs[i];//&((*it).first);
    }

}
